// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: tianqiang

#pragma once

#include <memory>
#include <sstream>
#include <string>

#include "coin2/exchange/base/symbology/spot_product.h"
#include "coin2/exchange/bittrex/symbology/currency.h"

namespace coin2::exchange::bittrex::symbology {

class BittrexProduct : public base::symbology::SpotProduct<BittrexCurrency, BittrexProduct>,
                       public base::symbology::ProductFromStrMixin<BittrexProduct> {
 public:
  BittrexProduct(const BittrexCurrency& base, const BittrexCurrency& quote)
      : SpotProduct(
            base,
            quote,
            ToNativeProduct(base, quote),
            ToNativeProduct(base, quote),
            base::market::ExchangeType::Bittrex) {}

 public:
  static std::unique_ptr<BittrexProduct> FromNativeStrImpl(
      const std::string& native_product,
      int64_t resolve_timestamp) {
    std::unique_ptr<BittrexCurrency> base_ptr;
    std::unique_ptr<BittrexCurrency> quote_ptr;
    bool success = ParseNativeProduct(native_product, resolve_timestamp, &base_ptr, &quote_ptr);

    if (!success) {
      return {};
    }

    return std::make_unique<BittrexProduct>(*base_ptr, *quote_ptr);
  }

 private:
  static bool ParseNativeProduct(
      const std::string& product_str,
      int64_t resolve_timestamp,
      std::unique_ptr<BittrexCurrency>* base_ptr,
      std::unique_ptr<BittrexCurrency>* quote_ptr) {
    std::vector<std::string> splitted = Split(product_str, "-");

    if (splitted.size() != 2) {
      return false;
    }

    std::string base = splitted[0];
    std::string quote = splitted[1];

    *base_ptr = BittrexCurrency::FromNativeStrNoThrow(base, resolve_timestamp);
    *quote_ptr = BittrexCurrency::FromNativeStrNoThrow(quote, resolve_timestamp);

    return true;
  }

  static std::string ToNativeProduct(const BittrexCurrency& base, const BittrexCurrency& quote) {
    using base::market::MarketType;
    std::stringstream ss;
    ss << base.native_currency(MarketType::Spot) << "-" << quote.native_currency(MarketType::Spot);
    return ss.str();
  }
};

}  // namespace coin2::exchange::bittrex::symbology
